﻿
using System;

using SubSonic;

using NUnit.Framework;

namespace TestDB.Data.Test
{
    [TestFixture]
    public sealed class TestFaultItemDAO
    {
        // ************************************************* //
        #region [ member variables ]

        private static Random m_rand = new Random();
        private static int m_counter = 0;

        #endregion

        // ************************************************* //
        #region [ helper ]

        /// <summary>
        /// clear all rows in the table to restore an initial state
        /// </summary>
        [SetUp]
        public void Setup()
        {
            new Delete().From(FaultItem.Schema).Execute();
        }

        public static FaultItem NewFaultItem()
        {
            ++m_counter;
            return new FaultItem
            {
                Name = string.Format("faultitem-{0}", m_counter.ToString()),
                FaultType = m_rand.Next(1, 100),
                Time = m_rand.NextDouble(),
                FaultValue = m_rand.NextDouble()
            };
        }

        #endregion

        // ************************************************* //
        #region [ test ]

        [Test]
        public void TestGenerateId()
        {
            FaultItem item1 = NewFaultItem();
            Assert.AreEqual(0, item1.FaultItemId);

            item1.GenerateId();
            Assert.IsTrue(item1.FaultItemId > 0);
        }

        [Test]
        public void TestInsertSingle()
        {
            // ------------------------- insert
            FaultItem newItem = NewFaultItem();
            newItem.Save();

            // ------------------------- retrieve
            FaultItem cpyItem = FaultItem.FetchByID(newItem.FaultItemId);
            Assert.AreNotSame(cpyItem, newItem);
            Assert.AreEqual(cpyItem, newItem);
        }

        [Test]
        public void TestUpdateSingle()
        {
            // ----------------- insert
            FaultItem oriItem = NewFaultItem();
            oriItem.Save();

            // ----------------- retrieve
            FaultItem cpyItem = FaultItem.FetchByID(oriItem.FaultItemId);

            // ----------------- change
            oriItem.Time += 1;
            oriItem.FaultType += 2;
            Assert.AreNotEqual(oriItem, cpyItem);

            // ----------------- update
            oriItem.Save();

            // ----------------- retrieve again
            cpyItem = FaultItem.FetchByID(oriItem.FaultItemId);
            Assert.AreEqual(oriItem, cpyItem);
        }

        [Test]
        public void TestDeleteSingle()
        {
            // ----------------- insert
            FaultItem item = NewFaultItem();
            item.Save();

            // ----------------- retrieve
            FaultItem cpyitem = FaultItem.FetchByID(item.FaultItemId);
            Assert.AreEqual(cpyitem, item);

            // ----------------- delete
            FaultItem.Delete(item.FaultItemId);

            // ----------------- retrieve again
            cpyitem = FaultItem.FetchByID(item.FaultItemId);
            Assert.IsNull(cpyitem);
        }

        [Test]
        public void TestRetrieveMaxId()
        {
            // ------------- check that table has been cleared empty in "setup"
            Assert.AreEqual(0, DB.Select().From(FaultItem.Schema).GetRecordCount());

            // ------------- check that when table is empty, maxid will return zero
            SqlQuery findMaxIdCmd = DB.Select(Aggregate.Max(FaultItem.Columns.FaultItemId)).From(FaultItem.Schema);
            int maxIdWhenEmpty = findMaxIdCmd.ExecuteScalar<int>();
            Assert.AreEqual(0, maxIdWhenEmpty);

            // ------------- insert a new item and check again
            FaultItem newItem = NewFaultItem();
            newItem.Save();

            Assert.IsTrue(newItem.FaultItemId > 0);

            int maxIdNow = findMaxIdCmd.ExecuteScalar<int>();
            Assert.AreEqual(newItem.FaultItemId, maxIdNow);
        }

        #endregion
    }
}